import axios from "axios";
import type {
  AxiosError,
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import event, { EventNames } from "@/api/eventEmitter.ts";
import { RequestEnum } from "@/common/canstant";
import type { ResultData } from "@/api/interface";

class Curl {
  private service: AxiosInstance;

  constructor(config: AxiosRequestConfig) {
    this.service = axios.create(config);
    this.setRequestInterceptors();
    this.setResponseInterceptors();
  }

  // 请求拦截器
  private setRequestInterceptors() {
    this.service.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        const token = localStorage.getItem("token");
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );
  }

  // 响应拦截器
  private setResponseInterceptors() {
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        const { data } = response;

        if (data.code === RequestEnum.TIMEOUT) {
          event.emit(EventNames.API_TIMEOUT);
          return Promise.reject(data);
        }

        if (data.code !== RequestEnum.SUCCESS) {
          event.emit(EventNames.API_INVALID);
          return Promise.reject(data);
        }

        return data;
      },
      (error: AxiosError) => {
        event.emit(EventNames.API_NETWORK_ERROR);
        return Promise.reject(error);
      }
    );
  }

  get<T>(url: string, params?: object): Promise<ResultData<T>> {
    return this.service.get(url, { params });
  }

  post<T>(url: string, data?: object): Promise<ResultData<T>> {
    return this.service.post(url, data);
  }

  put<T>(url: string, data?: object): Promise<ResultData<T>> {
    return this.service.put(url, data);
  }

  delete<T>(url: string, params?: object): Promise<ResultData<T>> {
    return this.service.delete(url, { params });
  }
}

const config: AxiosRequestConfig = {
  baseURL: import.meta.env.VITE_API_URL as string,
  timeout: RequestEnum.TIMEOUT as number,
  withCredentials: true,
};

const curl = new Curl(config);

export default curl;
